<template>
  <div v-show="config.visible" :class="['llm-dialog-page', `ld-theme-${config.theme}`]">
    <div class="llm-dialog-box">
      <div ref="scrollContainer" class="llm-dialog-scroll-container">
        <div class="llm-dialog-content">
          <DialogMessage :messages="messages" />
          <DialogInput />
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts" name="LLMDialog">
import '@/styles/github.css'
import '@/styles/variable.css'
import DialogMessage from './DialogMessage.vue'
import DialogInput from './DialogInput.vue'
import type {
  LDConfigReactive,
  LDEmits,
  LDEvents,
  LDStateReactive,
  LDTheme,
  LDMessage,
  LDFile,
} from '@/llmDialog/types'
import { computed, provide, reactive, ref, nextTick } from 'vue'
import useAutoScrollToBottom from '@/hooks/autoScrollToBottom'

// 接收参数
const editorText = defineModel({ default: '', type: String })
const props = defineProps({
  // 组件是否可见
  visible: {
    type: Boolean,
    default: true,
  },
  // 组件主题
  theme: {
    type: String as () => LDTheme,
    default: 'light',
  },
  // 消息列表
  messages: {
    type: Array as () => LDMessage[],
    default: () => [],
  },
  // 文件列表
  files: {
    type: Array as () => LDFile[],
    default: () => [],
  },
  // 文件数量限制
  maxFileCount: {
    type: Number,
    default: 5,
  },
  // 单文件大小限制
  maxPerFileSize: {
    type: Number,
    default: 10 * 1024 * 1024, // 10MB
  },
  // 总文件大小限制
  maxTotalFileSize: {
    type: Number,
    default: 50 * 1024 * 1024, // 50MB
  },
})

// 状态
const state = reactive({
  editorText,
  isSending: false,
  messages: computed(() => props.messages),
  files: computed(() => props.files),
})

provide<LDStateReactive>('state', state)

// 配置
const config = reactive({
  visible: props.visible,
  theme: props.theme,
  maxFileCount: props.maxFileCount,
  maxPerFileSize: props.maxPerFileSize,
  maxTotalFileSize: props.maxTotalFileSize,
})

provide<LDConfigReactive>('config', config)

// 事件
const emit = defineEmits<LDEmits>()

const events = {
  send: (text: string, files: File[], append: (text: string) => void, done: () => void) =>
    emit('send', text, files, append, done),
  stop: () => emit('stop'),
  theme: (newTheme: LDTheme, oldTheme: LDTheme) => emit('theme', newTheme, oldTheme),
  uploadFiles: (files: FileList) => emit('upload-files', files),
  deleteFile: (file: File) => emit('delete-file', file),
  clearFiles: (files: File[]) => emit('clear-files', files),
}

provide<LDEvents>('events', events)

// 滚动容器引用
const scrollContainer = ref<HTMLElement | null>(null)

const { scrollToBottom, isAtBottom } = useAutoScrollToBottom(scrollContainer)

provide('scroll-context', { scrollToBottom, isAtBottom })
</script>

<style>
.ld-svg-icon {
  fill: var(--ld-color-text);
  transition: fill var(--ld-transition-duration) ease;
}

.llm-dialog-page {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  background-color: var(--ld-color-bg);
  transition:
    background-color var(--ld-transition-duration),
    color var(--ld-transition-duration);
}

.llm-dialog-page ::-webkit-scrollbar {
  width: 6px !important;
  height: 6px !important;
}

.llm-dialog-page ::-webkit-scrollbar-thumb {
  border-radius: 3px !important;
  background: #c1c1c1 !important;
}

.llm-dialog-box {
  flex-grow: 1;
  position: relative;
}

.llm-dialog-scroll-container {
  min-height: 100%;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  overflow: auto;
  scroll-behavior: smooth;
}

.llm-dialog-content {
  display: flex;
  flex-direction: column;
  position: relative;
  height: 100%;
}
</style>
